<template>
  <div class="test-plan-dashboard">
    <!-- 顶部操作区 -->
    <div class="dashboard-header">
      <div class="dashboard-title">
        <h2>测试计划管理</h2>
      </div>
      <div class="dashboard-actions">
        <el-input 
          v-model="filterText" 
          placeholder="搜索计划" 
          prefix-icon="el-icon-search"
          clearable
          class="search-input"
          @keyup.enter="handletreeClick"
        >
          <template #append>
            <el-button @click="handletreeClick">
              <el-icon><Search /></el-icon>
            </el-button>
          </template>
        </el-input>
        <el-button 
          type="success" 
          :disabled="!scene_list || scene_list.length === 0 || !planId" 
          @click="runPlan"
          class="run-button"
        >
          运行计划
        </el-button>
      </div>
    </div>

    <!-- 主体内容区 -->
    <div class="dashboard-main" v-loading="loading">
      <!-- 左侧测试计划列表 -->
      <div class="plans-sidebar">
        <div class="sidebar-header">
          <h3>测试计划列表</h3>
          <el-button 
            type="primary" 
            size="small" 
            @click="addPlan"
            class="add-plan-btn"
          >
            新建计划
          </el-button>
        </div>
        
        <el-empty 
          v-if="planList.length === 0" 
          description="暂无测试计划" 
          :image-size="100"
        >
          <el-button type="primary" @click="addPlan">创建计划</el-button>
        </el-empty>
          <div class="plans-list">
            <div 
              v-for="item in planList" 
              :key="item.id" 
              :class="['plan-item', { active: planId === item.id }]"
              @click="selectPlan(item.id)"
            >
              <div class="plan-info">
                <el-icon><Folder /></el-icon>
                <span class="plan-name">{{ item.name }}</span>
              </div>
              <div class="plan-actions">
                <el-tooltip content="编辑" placement="top">
                  <el-icon 
                    @click.stop="editPlan(item)" 
                    class="action-icon"
                  >
                    <Edit />
                  </el-icon>
                </el-tooltip>
                <el-tooltip content="删除" placement="top">
                  <el-icon 
                    @click.stop="delPlan(item.id)" 
                    class="action-icon delete-icon"
                  >
                    <Delete />
                  </el-icon>
                </el-tooltip>
              </div>
            </div>
          </div>
      </div>
      
      <!-- 右侧主要内容区 -->
      <div class="content-main">
        <!-- 没有测试计划时显示 -->
        <el-empty 
          v-if="planList.length === 0" 
          description="暂无测试计划，请先创建测试计划" 
          class="center-empty">
          <el-button type="primary" @click="addPlan">创建测试计划</el-button>
        </el-empty>
        
        <!-- 有测试计划但没有场景时显示 -->
        <el-empty 
          v-else-if="!scene_list || scene_list.length === 0" 
          description="当前计划暂无测试场景" 
          class="center-empty">
          <el-button type="primary" @click="clickAddScene">添加测试场景</el-button>
        </el-empty>
        
        <!-- 有测试场景时显示 -->
        <div v-else class="content-layout">
          <!-- 测试场景区域 -->
          <div class="scenes-container">
            <div class="section-header">
              <h3>
                <span v-if="currentPlanName">{{ currentPlanName }}</span>
                <span v-else>测试场景</span>
              </h3>
              <el-button 
                type="primary" 
                size="small" 
                @click="clickAddScene"
                class="add-scene-btn"
              >
                添加场景
              </el-button>
            </div>
            
            <div class="scenes-grid">
              <div v-for="(item, index) in scene_list" :key="item.id" class="scene-card" @click="clickView(item)">
                <div class="scene-status">
                  <div :class="['status-indicator', item.stepCount > 0 ? 'ready' : 'pending']"></div>
                </div>
                <div class="scene-card-content">
                  <div class="scene-card-header">
                    <h4>{{ item.name }}</h4>
                    <el-dropdown trigger="hover" @command="handleSceneCommand" @click.stop>
                      <span class="scene-more">
                        <el-icon><MoreFilled /></el-icon>
                      </span>
                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item :command="{type: 'delete', id: item.id}">
                            <el-icon><Delete /></el-icon> 删除场景
                          </el-dropdown-item>
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </div>
                  <div class="scene-card-description">
                    {{ item.desc || '暂无描述' }}
                  </div>
                  <div class="scene-card-footer">
                    <div class="scene-steps">
                      <el-icon><Document /></el-icon>
                      <span>{{ item.stepCount || 0 }} 步骤</span>
                    </div>
                    <div class="scene-actions">
                      <div class="scene-number">场景 #{{ index + 1 }}</div>
                      <el-button 
                        size="small" 
                        type="danger" 
                        circle 
                        class="delete-scene-btn"
                        @click.stop="delScene(item.id)"
                        title="删除场景"
                      >
                        <el-icon><Delete /></el-icon>
                      </el-button>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          
          <!-- 右侧测试数据区域 -->
          <div class="data-container">
            <div class="data-overview">
              <div class="data-card pass-rate">
                <div class="data-value">{{ getAveragePassRate() }}%</div>
                <div class="data-label">平均通过率</div>
              </div>
              <div class="data-card total-runs">
                <div class="data-value">{{ records.length }}</div>
                <div class="data-label">总执行次数</div>
              </div>
              <div class="data-card success-runs">
                <div class="data-value">{{ getSuccessfulRuns() }}</div>
                <div class="data-label">成功执行</div>
              </div>
            </div>
            
            <!-- 通过率趋势图 -->
            <div class="chart-section">
              <div class="section-header">
                <h3>通过率趋势</h3>
                <div class="chart-legend">
                  <div class="legend-item">
                    <div class="legend-color success"></div>
                    <div class="legend-text">通过率</div>
                  </div>
                </div>
              </div>
              <div class="chart-container-wrapper">
                <div ref="chartTable" class="chart-container"></div>
              </div>
            </div>
            
            <!-- 执行记录表格 -->
            <div class="records-section">
              <div class="section-header">
                <h3>执行记录</h3>
                <el-tag type="info" size="small">近三天</el-tag>
              </div>
              <div class="records-container">
                <el-table 
                  :data="records" 
                  stripe 
                  style="width: 100%" 
                  size="small"
                  :empty-text="'暂无执行记录'"
                  class="records-table"
                >
                  <el-table-column label="执行时间" min-width="120">
                    <template #default="scope">
                      <div class="time-cell">
                        <el-icon><Timer /></el-icon>
                        <span>{{ $tools.rTime(scope.row.create_time) }}</span>
                      </div>
                    </template>
                  </el-table-column>
                  
                  <el-table-column label="环境" width="100">
                    <template #default="scope">
                      <el-tag size="small" effect="plain">{{ scope.row.env_name }}</el-tag>
                    </template>
                  </el-table-column>
                  
                  <el-table-column label="状态" width="100">
                    <template #default="scope">
                      <div class="status-cell">
                        <div v-if="scope.row.status === '执行中'" class="status-badge running">
                          <div class="status-indicator-dot"></div>
                          <span>执行中</span>
                        </div>
                        <div v-else class="status-badge completed">
                          <el-icon><Check /></el-icon>
                          <span>已完成</span>
                        </div>
                      </div>
                    </template>
                  </el-table-column>
                  
                  <el-table-column label="结果" min-width="120">
                    <template #default="scope">
                      <template v-if="scope.row.status !== '执行中'">
                        <div class="progress-wrapper">
                          <div class="progress-counts">
                            <span class="success-count">{{ scope.row.success }}</span>
                            <span class="total-count">/ {{ scope.row.all }}</span>
                            <span class="progress-percentage">{{ scope.row.pass_rate }}%</span>
                          </div>
                          <el-progress 
                            :percentage="parseFloat(scope.row.pass_rate)" 
                            :stroke-width="6" 
                            :color="getProgressColor(scope.row.pass_rate)"
                          ></el-progress>
                        </div>
                      </template>
                      <template v-else>
                        <div class="progress-pending">
                          <el-icon><Loading /></el-icon>
                          <span>进行中...</span>
                        </div>
                      </template>
                    </template>
                  </el-table-column>
                  
                  <el-table-column label="报告" width="80" fixed="right">
                    <template #default="scope">
                      <el-button 
                        v-if="scope.row.status !== '执行中'" 
                        type="primary" 
                        link
                        @click="$router.push({ name: 'report', params: { id: scope.row.id } })"
                      >
                        查看
                      </el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 修改计划窗口 -->
    <el-dialog 
      v-model="editDlg" 
      :title="planForm.id ? '编辑测试计划' : '新建测试计划'" 
      width="30%" 
      :before-close="clickClear"
      destroy-on-close
      top="20vh"
      class="plan-dialog"
    >
      <el-form :model="planForm" ref="treeRef" label-position="top">
        <el-form-item label="计划名称" prop="name" :rules="[{ required: true, message: '请输入计划名称', trigger: 'blur' }]">
          <el-input 
            v-model="planForm.name" 
            placeholder="请输入计划名称" 
            clearable
            autofocus
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="clickClear">取消</el-button>
          <el-button type="primary" @click="savePlan">保存</el-button>
        </span>
      </template>
    </el-dialog>
    
    <!-- 添加测试场景窗口 -->
    <TestCase v-if="sceneDlg" @close-modal="handleCloseModal" :planId="planId"></TestCase>
  </div>
</template>

<script>
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
import {mapMutations, mapState} from "vuex";
import { Icon } from '@iconify/vue'
import TestCase from '../../views/TestPlan/TestCaseDlg.vue';
export default {
  components: {
    Icon,
    TestCase
  },
  data() {
    return {
      // 测试计划列表
			planList: [],
			// 当前选中的测试计划ID
			planId: '',
			// 测试计划中所有运行记录
			records: [],
      // 表单数据
      planForm:{
        name: '',
        id: null
      },
      // 搜索关键词
      filterText: '',
      // 对话框控制
      editDlg: false,
      // 测试场景列表
      scene_list: [],
      // 场景对话框控制
      sceneDlg: false,
      // 加载状态
      loading: false,
      // 当前选中的计划名称
      currentPlanName: '',
      // 颜色配置
      themeColors: {
        success: '#67C23A',
        warning: '#E6A23C',
        danger: '#F56C6C',
        info: '#909399'
      }
    }
  },
  computed: {
    ...mapState(['pro', 'envId']),
    defaultProps() {
      return {
        children: 'children',
        label: 'name',
      }
    },
    chartData: function() {
			let runDate = [];
			let passRate = [];

			for (let item of this.records) {
				runDate.push(this.$tools.rTime(item.create_time));
				passRate.push(parseFloat(item.pass_rate).toFixed(2));
			}
			return {
				label: runDate.reverse(),
				value: passRate
			};
		},
  },
  methods: {
    ...mapMutations(['CaseInfo']),
    
    // 获取测试计划列表
    async getAllPlan(name) {
      this.loading = true;
      try {
        let response;
        if(name) {
          response = await this.$api.getTestPlan(this.pro.id, name);
        } else {
          response = await this.$api.getTestPlan(this.pro.id);
        }
        
        if (response.status === 200) {
          this.planList = response.data;
          
          // 设置默认激活的测试计划并获取数据
          if (this.planList.length > 0) {
            if (!this.planId || !this.planList.find(plan => plan.id === this.planId)) {
              this.selectPlan(this.planList[0].id);
            } else {
              // 更新当前计划名称
              this.updateCurrentPlanName();
            }
          } else {
            this.planId = '';
            this.currentPlanName = '';
            this.scene_list = [];
            this.records = [];
          }
        }
      } catch (error) {
        ElMessage({
          type: 'error',
          message: '获取测试计划失败',
          duration: 1500
        });
        console.error('获取测试计划失败', error);
      } finally {
        this.loading = false;
      }
    },

    // 更新当前计划名称
    updateCurrentPlanName() {
      if (this.planId) {
        const currentPlan = this.planList.find(plan => plan.id === this.planId);
        if (currentPlan) {
          this.currentPlanName = currentPlan.name;
        }
      } else {
        this.currentPlanName = '';
      }
    },

    // 获取测试计划所有的执行记录
    async getAllRecord() {
      try {
        const response = await this.$api.getTestRecord({ plan: this.planId, project: this.pro.id });
        if (response.status === 200) {
          this.records = response.data;
        }
      } catch (error) {
        console.error('获取执行记录失败', error);
      }
    },
    
    // 选择测试计划
    selectPlan(planId) {
      if (this.planId !== planId) {
        this.planId = planId;
        this.updateCurrentPlanName();
        this.getScenes(planId);
      }
    },
    
    // 添加测试计划
    async addPlan() {
      this.planForm = {
        name: '新测试计划',
        id: null
      };
      this.editDlg = true;
    },
    
    // 编辑测试计划
    editPlan(plan) {
      this.planForm = {...plan};
      this.editDlg = true;
    },
    
    // 处理节点点击
    handleNodeClick(data) {
      this.selectPlan(data.id);
    },
    
    // 获取测试场景
    async getScenes(planId) {
      this.loading = true;
      try {
        const response = await this.$api.getTestCase_({
          testplan: planId
        });
        if (response.status === 200) {
          this.scene_list = response.data.result;
        }
        this.getAllRecord();
      } catch (error) {
        ElMessage({
          type: 'error',
          message: '获取测试场景失败',
          duration: 1500
        });
        console.error('获取测试场景失败', error);
      } finally {
        this.loading = false;
      }
    },
    
    // 点击查询
    handletreeClick() {
      this.getAllPlan(this.filterText);
    },

    // 点击取消
    clickClear() {
      this.editDlg = false;
    },
    
    // 保存测试计划
    async savePlan() {
      if (!this.planForm.name) {
        ElMessage({
          type: 'warning',
          message: '请输入计划名称',
          duration: 1500
        });
        return;
      }
      
      try {
        let response;
        if (this.planForm.id) {
          // 更新现有计划
          response = await this.$api.updateTestPlan(this.planForm.id, this.planForm);
        } else {
          // 创建新计划
          const params = {
            project: this.pro.id,
            name: this.planForm.name
          };
          response = await this.$api.createTestPlan(params);
        }
        
        if (response.status === 200 || response.status === 201) {
          ElMessage({
            type: 'success',
            message: this.planForm.id ? '保存成功' : '创建成功',
            duration: 1500
          });
          this.editDlg = false;
          await this.getAllPlan();
          
          // 如果是新建的计划，选中它
          if (!this.planForm.id && response.data && response.data.id) {
            this.selectPlan(response.data.id);
          } else if (this.planForm.id === this.planId) {
            // 如果修改的是当前计划，更新名称
            this.updateCurrentPlanName();
          }
        }
      } catch (error) {
        ElMessage({
          type: 'error',
          message: '操作失败',
          duration: 1500
        });
        console.error('保存计划失败', error);
      }
    },
    
    // 运行测试计划
    async runPlan() {
      if (!this.planId) {
        ElMessage({
          type: 'warning',
          message: '请先选择测试计划',
          duration: 1500
        });
        return;
      }
      
      if (this.envId) {
        const params = {
          env: this.envId,
          plan: this.planId,
          types: 2
        };
        
        ElNotification({
          title: '开始运行',
          message: '测试计划正在执行中，请稍候...',
          type: 'success',
          duration: 3000
        });
        
        try {
          const response = await this.$api.runPlan(this.planId, params);
          if (response.status === 200) {
            this.getAllRecord();
          }
        } catch (error) {
          ElMessage({
            type: 'error',
            message: '运行计划失败',
            duration: 1500
          });
          console.error('运行计划失败', error);
        }
      } else {
        ElMessage({
          type: 'warning',
          message: '当前未选中执行环境!',
          duration: 1500
        });
      }
    },
    
    // 删除测试计划
    delPlan(id) {
      ElMessageBox.confirm('确定要删除该测试计划吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          try {
            const response = await this.$api.delTestPlan(id);
            if (response.status === 204) {
              ElMessage({
                type: 'success',
                message: '删除成功',
                duration: 1500
              });
              
              // 重新获取计划列表
              await this.getAllPlan();
              
              // 如果删除的是当前选中的计划，重置选择
              if (id === this.planId) {
                this.planId = this.planList.length > 0 ? this.planList[0].id : '';
                if (this.planId) {
                  this.getScenes(this.planId);
                } else {
                  this.scene_list = [];
                  this.records = [];
                }
              }
            }
          } catch (error) {
            ElMessage({
              type: 'error',
              message: '删除失败',
              duration: 1500
            });
            console.error('删除计划失败', error);
          }
        })
        .catch(() => {
          ElMessage({
            type: 'info',
            message: '已取消删除',
            duration: 1500
          });
        });
    },

    // 点击查看测试场景详情
    clickView(item) {
      this.$router.push({ name: 'TestCaseDetail' });
      item.back_type = 'plan';
      this.CaseInfo(item);
    },

    // 处理场景命令
    handleSceneCommand(command) {
      if (command.type === 'delete') {
        this.delScene(command.id);
      }
    },

    // 删除测试场景
    async delScene(id) {
      try {
        let params = { scene_id: id };
        const response = await this.$api.delTestPlan_scene(this.planId, params);
        if (response.status === 200) {
          ElMessage({
            type: 'success',
            message: '删除成功',
            duration: 1500
          });
          // 更新页面中当前任务的数据
          this.getScenes(this.planId);
        }
      } catch (error) {
        ElMessage({
          type: 'error',
          message: '删除失败',
          duration: 1500
        });
        console.error('删除场景失败', error);
      }
    },
    
    // 点击添加场景
    clickAddScene() {
      this.sceneDlg = true;
    },

    // 处理关闭模态框
    handleCloseModal() {
      this.sceneDlg = false; // 关闭弹窗
      this.getScenes(this.planId);
    },
    
    // 获取平均通过率
    getAveragePassRate() {
      if (!this.records || this.records.length === 0) {
        return 0;
      }
      
      const completedRecords = this.records.filter(record => record.status !== '执行中');
      if (completedRecords.length === 0) {
        return 0;
      }
      
      const totalPassRate = completedRecords.reduce((sum, record) => sum + parseFloat(record.pass_rate), 0);
      return (totalPassRate / completedRecords.length).toFixed(2);
    },
    
    // 获取成功执行次数
    getSuccessfulRuns() {
      if (!this.records) return 0;
      return this.records.filter(record => record.status !== '执行中' && parseFloat(record.pass_rate) >= 80).length;
    },
    
    // 获取进度条颜色
    getProgressColor(rate) {
      const percentage = parseFloat(rate);
      if (percentage >= 80) {
        return this.themeColors.success;
      } else if (percentage >= 60) {
        return this.themeColors.warning;
      } else {
        return this.themeColors.danger;
      }
    }
  },
  created() {
    this.getAllPlan();
  },
  watch: {
    records() {
      // 渲染通过率趋势图
      this.$nextTick(() => {
        if (this.$refs.chartTable) {
          this.$chart.chart3(this.$refs.chartTable, this.chartData.value, this.chartData.label);
        }
      });
    }
  }
}
</script>

<style scoped>
/* 主容器样式 */
.test-plan-dashboard {
  height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
  color: #333;
  font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
  background-image: linear-gradient(rgba(255, 255, 255, 0.7) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255, 255, 255, 0.7) 1px, transparent 1px);
  background-size: 20px 20px;
  background-position: center center;
  overflow: hidden; /* 防止整体出现滚动条 */
}

/* 头部样式 */
.dashboard-header {
  padding: 20px 28px;
  background: linear-gradient(135deg, #ffffff 0%, #f5f7fa 100%);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 10;
  border-bottom: 1px solid rgba(0, 0, 0, 0.03);
  flex-shrink: 0; /* 防止头部被压缩 */
}

.dashboard-title {
  display: flex;
  align-items: center;
  gap: 24px;
}

.dashboard-title h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: #1f2329;
  position: relative;
  padding-left: 16px;
}

.dashboard-title h2:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 20px;
  background: linear-gradient(to bottom, #409EFF, #53a8ff);
  border-radius: 2px;
}

.dashboard-actions {
  display: flex;
  align-items: center;
  gap: 20px;
}

.search-input {
  width: 260px;
  transition: all 0.3s ease;
}

.search-input:hover, .search-input:focus-within {
  box-shadow: 0 0 8px rgba(64, 158, 255, 0.1);
}

.run-button {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  font-weight: 500;
  transition: all 0.3s ease;
  border-radius: 8px;
  letter-spacing: 0.5px;
}

.run-button:not(:disabled):hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(103, 194, 58, 0.2);
}

/* 主内容区域 */
.dashboard-main {
  flex: 1;
  display: flex;
  gap: 20px;
  padding: 20px;
  overflow: auto; /* 允许主区域滚动 */
  position: relative;
}

/* 计划列表侧边栏 */
.plans-sidebar {
  width: 280px;
  background: linear-gradient(135deg, #ffffff 0%, #f9fbfd 100%);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: all 0.3s ease;
  position: relative;
  flex-shrink: 0; /* 防止侧边栏被压缩 */
  max-height: calc(100vh - 120px); /* 限制最大高度 */
}

.plans-sidebar:hover {
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
}

.plans-sidebar:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, #409EFF, #79bbff);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.plans-sidebar:hover:before {
  opacity: 1;
}

.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #f0f2f5;
  background-color: rgba(64, 158, 255, 0.03);
}

.sidebar-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1f2329;
  position: relative;
  padding-left: 12px;
}

.sidebar-header h3:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 14px;
  background: linear-gradient(to bottom, #409EFF, #53a8ff);
  border-radius: 2px;
}

.add-plan-btn {
  padding: 8px 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.add-plan-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(64, 158, 255, 0.15);
}


.plans-list {
  padding: 12px;
  overflow-y: auto; /* 允许计划列表滚动 */
  flex: 1; /* 使列表可以占满剩余空间 */
}

.plan-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 14px;
  margin-bottom: 6px;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s ease;
  border: 1px solid transparent;
  background-color: rgba(255, 255, 255, 0.6);
}

.plan-item:hover {
  background-color: rgba(64, 158, 255, 0.05);
  border-color: rgba(64, 158, 255, 0.1);
  transform: translateX(4px);
}

.plan-item.active {
  background-color: rgba(64, 158, 255, 0.1);
  color: #409eff;
  border-left: 3px solid #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}

.plan-info {
  display: flex;
  align-items: center;
  gap: 10px;
  overflow: hidden;
}

.plan-info .el-icon {
  font-size: 18px;
  color: #409eff;
  opacity: 0.8;
  transition: all 0.3s ease;
}

.plan-item:hover .plan-info .el-icon {
  opacity: 1;
  transform: scale(1.1);
}

.plan-name {
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: all 0.3s ease;
}

.plan-item.active .plan-name {
  font-weight: 600;
  letter-spacing: 0.5px;
}

.plan-actions {
  display: none;
  gap: 8px;
}

.plan-item:hover .plan-actions {
  display: flex;
}

.action-icon {
  font-size: 16px;
  color: #909399;
  cursor: pointer;
  padding: 4px;
  border-radius: 4px;
  transition: all 0.3s ease;
  background-color: rgba(255, 255, 255, 0.5);
}

.action-icon:hover {
  color: #409eff;
  background-color: rgba(64, 158, 255, 0.1);
  transform: scale(1.1);
}

.delete-icon:hover {
  color: #f56c6c;
  background-color: rgba(245, 108, 108, 0.1);
}

/* 内容主区域 */
.content-main {
  flex: 1;
  overflow: auto; /* 允许右侧主要内容区域滚动 */
  position: relative;
  display: flex; /* 使其内容可以灵活排布 */
  flex-direction: column; /* 垂直排列内容 */
}

.center-empty {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  width: 100%;
  max-width: 400px;
}

.center-empty .el-button {
  margin-top: 16px;
  transition: all 0.3s ease;
}

.center-empty .el-button:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 15px rgba(64, 158, 255, 0.2);
}

/* 布局 */
.content-layout {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 20px;
  height: auto; /* 改为自适应高度 */
  min-height: 100%; /* 至少占满容器高度 */
  overflow: visible; /* 不隐藏溢出内容 */
}

/* 场景区域 */
.scenes-container {
  display: flex;
  flex-direction: column;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  padding: 16px;
  overflow: hidden;
  height: auto; /* 改为自适应高度 */
  min-height: 400px; /* 设置最小高度 */
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.section-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1f2329;
}

.scenes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
  overflow-y: auto; /* 允许场景网格滚动 */
  padding-right: 8px;
  flex: 1; /* 占满剩余空间 */
  max-height: calc(100vh - 250px); /* 限制最大高度 */
}

.scene-card {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  display: flex;
  height: 160px;
  overflow: hidden;
  transition: all 0.3s ease;
  cursor: pointer;
  border: 1px solid #ebeef5;
  position: relative;
}

.scene-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 20px rgba(0, 0, 0, 0.1);
  border-color: #d0e2ff;
}

.scene-card:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #67C23A, #95D475);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.scene-card:hover:before {
  opacity: 1;
}

.scene-status {
  width: 8px;
  background: linear-gradient(to bottom, #f0f2f5, #e6e6e6);
}

.status-indicator {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-top: 16px;
  margin-left: -5px;
  transition: all 0.3s ease;
}

.status-indicator.ready {
  background-color: #67C23A;
  box-shadow: 0 0 0 4px rgba(103, 194, 58, 0.2);
}

.status-indicator.pending {
  background-color: #E6A23C;
  box-shadow: 0 0 0 4px rgba(230, 162, 60, 0.2);
}

.scene-card:hover .status-indicator.ready {
  box-shadow: 0 0 0 6px rgba(103, 194, 58, 0.25);
}

.scene-card:hover .status-indicator.pending {
  box-shadow: 0 0 0 6px rgba(230, 162, 60, 0.25);
}

.scene-card-content {
  flex: 1;
  padding: 18px;
  display: flex;
  flex-direction: column;
  background: linear-gradient(135deg, #ffffff 0%, #f9fbfd 100%);
}

.scene-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 10px;
}

.scene-card-header h4 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1f2329;
  line-height: 24px;
  max-width: 85%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  position: relative;
  padding-bottom: 6px;
}

.scene-card-header h4:after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 30px;
  height: 2px;
  background-color: #409EFF;
  transition: width 0.3s ease;
}

.scene-card:hover .scene-card-header h4:after {
  width: 50px;
}

.scene-more {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  color: #606266;
  cursor: pointer;
  transition: all 0.3s ease;
  background-color: transparent;
}

.scene-more:hover {
  background-color: rgba(64, 158, 255, 0.1);
  color: #409EFF;
}

.scene-card-description {
  flex: 1;
  margin-bottom: 12px;
  font-size: 14px;
  color: #606266;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.5;
  position: relative;
  background: linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 75%, rgba(249,251,253,1) 100%);
  padding-bottom: 5px;
}

.scene-card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: #909399;
  padding-top: 8px;
  border-top: 1px dashed rgba(0, 0, 0, 0.05);
}

.scene-steps {
  display: flex;
  align-items: center;
  gap: 4px;
  background-color: rgba(64, 158, 255, 0.05);
  padding: 3px 8px;
  border-radius: 12px;
  transition: all 0.3s ease;
}

.scene-card:hover .scene-steps {
  background-color: rgba(64, 158, 255, 0.1);
}

.scene-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.scene-number {
  font-size: 12px;
  color: #409EFF;
  padding: 3px 10px;
  border-radius: 12px;
  background-color: rgba(64, 158, 255, 0.1);
  font-weight: 500;
  letter-spacing: 0.5px;
  transition: all 0.3s ease;
}

.scene-card:hover .scene-number {
  background-color: rgba(64, 158, 255, 0.2);
  box-shadow: 0 2px 5px rgba(64, 158, 255, 0.15);
}

.delete-scene-btn {
  opacity: 0;
  transform: scale(0.8);
  transition: all 0.3s ease;
  border: none;
  padding: 4px;
  background: rgba(245, 108, 108, 0.1);
  color: #F56C6C;
}

.scene-card:hover .delete-scene-btn {
  opacity: 1;
  transform: scale(1);
}

.delete-scene-btn:hover {
  background: rgba(245, 108, 108, 0.2);
  color: #F56C6C;
  transform: scale(1.1);
}

/* 右侧数据区域 */
.data-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
  overflow-y: visible; /* 避免整体滚动 */
  padding-right: 8px;
  height: auto; /* 自适应高度 */
  flex: 1; /* 占用可用空间 */
}

.data-overview {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.data-card {
  background: linear-gradient(135deg, #fff 0%, #f9fbfd 100%);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  padding: 20px;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 120px;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.data-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08);
}

.data-card:before {
  content: '';
  position: absolute;
  width: 100%;
  height: 4px;
  top: 0;
  left: 0;
  transition: all 0.3s ease;
}

.pass-rate:before {
  background: linear-gradient(90deg, #67C23A, #95D475);
}

.total-runs:before {
  background: linear-gradient(90deg, #409EFF, #79bbff);
}

.success-runs:before {
  background: linear-gradient(90deg, #67C23A, #95D475);
}

.data-value {
  font-size: 28px;
  font-weight: 600;
  margin-bottom: 10px;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.data-label {
  font-size: 14px;
  color: #606266;
  position: relative;
  padding-bottom: 4px;
}

.data-label:after {
  content: '';
  position: absolute;
  width: 20px;
  height: 2px;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  transition: width 0.3s ease;
}

.pass-rate .data-label:after {
  background-color: #67C23A;
}

.total-runs .data-label:after {
  background-color: #409EFF;
}

.success-runs .data-label:after {
  background-color: #67C23A;
}

.data-card:hover .data-label:after {
  width: 40px;
}

.chart-section {
  background: linear-gradient(135deg, #fff 0%, #f9fbfd 100%);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  padding: 20px;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 350px; /* 保持固定高度 */
  flex-shrink: 0; /* 防止被压缩 */
}

.chart-section:hover {
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
}

.chart-section:before {
  content: '';
  position: absolute;
  width: 100%;
  height: 4px;
  top: 0;
  left: 0;
  background: linear-gradient(90deg, #409EFF, #79bbff);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.chart-section:hover:before {
  opacity: 1;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px dashed rgba(0, 0, 0, 0.05);
}

.section-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1f2329;
  position: relative;
  padding-left: 12px;
}

.section-header h3:before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 14px;
  background: linear-gradient(to bottom, #409EFF, #53a8ff);
  border-radius: 2px;
}

.chart-legend {
  display: flex;
  gap: 12px;
  background-color: rgba(64, 158, 255, 0.05);
  padding: 4px 12px;
  border-radius: 20px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #606266;
}

.legend-color {
  width: 14px;
  height: 6px;
  border-radius: 3px;
}

.legend-color.success {
  background: linear-gradient(90deg, #67C23A, #95D475);
}

.chart-container-wrapper {
  height: 220px;
  margin-top: 12px;
  padding: 8px;
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 8px;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.02);
}

.chart-container {
  height: 100%;
  width: 100%;
}

.records-section {
  background: linear-gradient(135deg, #fff 0%, #f9fbfd 100%);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  padding: 20px;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex: 1; /* 占用剩余空间 */
}

.records-container {
  flex: 1;
  overflow: auto; /* 允许所有方向滚动 */
  position: relative;
  /* 增加内边距防止内容贴边 */
  padding-bottom: 10px;
}

.records-table {
  margin-top: 12px;
  border-radius: 8px;
  width: 100%;
  min-width: 100%; /* 确保表格至少占满容器宽度 */
}

/* 表格容器样式优化 */
.el-table {
  --el-table-header-background-color: rgba(64, 158, 255, 0.05);
  --el-table-border-color: rgba(0, 0, 0, 0.03);
  overflow: visible !important; /* 允许表格内容溢出 */
  border-radius: 8px;
}

.el-table::before {
  display: none;
}

.el-table th.el-table__cell {
  background-color: rgba(64, 158, 255, 0.05);
  color: #606266;
  font-weight: 600;
}

.el-table .el-table__row:hover > td.el-table__cell {
  background-color: rgba(64, 158, 255, 0.05);
}

/* 确保表格内容可以横向滚动 */
.records-container .el-table__body-wrapper {
  overflow-x: auto !important; /* 强制横向滚动 */
}

/* 状态和时间单元格样式 */
.time-cell {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-start;
  color: #606266;
}

.status-cell {
  display: flex;
  justify-content: center;
}

.status-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
}

.status-badge.running {
  color: #E6A23C;
  background-color: rgba(230, 162, 60, 0.15);
}

.status-badge.completed {
  color: #67C23A;
  background-color: rgba(103, 194, 58, 0.15);
}

.status-indicator-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: currentColor;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.5;
    transform: scale(1.1);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

.progress-wrapper {
  padding: 0 8px;
}

.progress-counts {
  display: flex;
  justify-content: flex-start;
  margin-bottom: 4px;
  font-size: 12px;
  gap: 4px;
  align-items: baseline;
}

.success-count {
  color: #67C23A;
  font-weight: bold;
  font-size: 14px;
}

.total-count {
  color: #909399;
}

.progress-percentage {
  color: #606266;
  margin-left: auto;
}

.progress-pending {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: #909399;
}

/* 对话框样式 */
.plan-dialog :deep(.el-dialog__body) {
  padding-top: 0;
}

/* 响应式调整 */
@media screen and (max-width: 1400px) {
  .content-layout {
    grid-template-columns: 1fr;
  }
  
  .data-container {
    flex-direction: row;
    flex-wrap: wrap;
    overflow-y: visible;
    overflow-x: hidden;
  }
  
  .data-overview {
    flex-basis: 100%;
  }
  
  .chart-section {
    flex-basis: calc(50% - 10px);
    height: 350px; /* 保持固定高度 */
  }
  
  .records-section {
    flex-basis: calc(50% - 10px);
    min-height: 350px;
  }
}

@media screen and (max-width: 1200px) {
  .dashboard-main {
    flex-direction: column;
    overflow-y: auto; /* 确保主内容区域可滚动 */
  }
  
  .plans-sidebar {
    width: 100%;
    height: auto;
    max-height: 300px;
    overflow-y: auto; /* 确保侧边栏可滚动 */
  }
  
  .plans-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 8px;
    max-height: none; /* 移除最大高度限制 */
    overflow-y: visible; /* 不再需要单独滚动 */
  }
  
  .plan-actions {
    display: flex;
  }
  
  .chart-section {
    height: 350px; /* 保持固定高度 */
  }
  
  .records-section {
    min-height: 350px;
  }
}

@media screen and (max-width: 768px) {
  .dashboard-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  
  .dashboard-actions {
    width: 100%;
    justify-content: space-between;
  }
  
  .scenes-grid {
    grid-template-columns: 1fr;
    max-height: none; /* 移除最大高度限制 */
  }
  
  .data-overview {
    grid-template-columns: 1fr;
  }
  
  .data-container {
    flex-direction: column;
    overflow-y: visible;
  }
  
  .chart-section {
    flex-basis: 100%;
    height: 350px; /* 保持固定高度 */
  }
  
  .records-section {
    flex-basis: 100%;
    min-height: 350px;
  }
}

/* 按钮图标与文字对齐修复 */
.el-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.el-button .el-icon {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 添加场景按钮和新建计划按钮样式 */
.add-scene-btn, .add-plan-btn {
  padding: 8px 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.add-scene-btn:hover, .add-plan-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(64, 158, 255, 0.15);
}

/* 表格容器样式优化 */
.el-table {
  --el-table-header-background-color: rgba(64, 158, 255, 0.05);
  --el-table-border-color: rgba(0, 0, 0, 0.03);
  overflow: hidden;
  border-radius: 8px;
}

.el-table::before {
  display: none;
}

.el-table th.el-table__cell {
  background-color: rgba(64, 158, 255, 0.05);
  color: #606266;
  font-weight: 600;
}

.el-table .el-table__row:hover > td.el-table__cell {
  background-color: rgba(64, 158, 255, 0.05);
}

/* 状态徽章增强 */
.status-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
}

.status-badge.running {
  color: #E6A23C;
  background-color: rgba(230, 162, 60, 0.15);
}

.status-badge.completed {
  color: #67C23A;
  background-color: rgba(103, 194, 58, 0.15);
}

/* 修复进度条样式 */
.el-progress-bar__outer {
  border-radius: 4px;
  background-color: rgba(0, 0, 0, 0.04);
}

.el-progress-bar__inner {
  border-radius: 4px;
  transition: all 0.3s ease;
}

/* 修正按钮图标对齐 */
.run-button, .add-plan-btn, .add-scene-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.run-button .el-icon,
.add-plan-btn .el-icon,
.add-scene-btn .el-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 4px;
}

/* 确保表格可以水平滚动的样式 */
:deep(.el-table__body-wrapper) {
  overflow-x: auto !important;
}

:deep(.el-table) {
  width: 100%;
  overflow: visible !important;
}

:deep(.el-table__inner-wrapper) {
  overflow: visible !important;
}
</style>
